package it.polito.connectedcar.trafficlight;

import it.polito.appeal.traci.connectedcar.trafficlight.ControlledLink;
import it.polito.connectedcar.ConnectedObject;
import it.polito.connectedcar.message.TrafficLightToTCCMessage;
import it.polito.connectedcar.trafficlight.network.TrafficLightNetworkConnectionManager;
import it.polito.connectedcar.util.Constants;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;

/**
 * This class is the highest representation of a TrafficLight connected into the
 * ConnectedCars system. It is in charge of preparing messages to be sent to the
 * TCC when the phase changes
 * 
 * 
 * @author Nicola Aresta
 * 
 */
public class ConnectedTrafficLight extends ConnectedObject implements TrafficLightUpdateDelegate {

	private SourceTrafficLightProxy sourceTrafficLight;
	private TrafficLightNetworkConnectionManager trafficLightsNetworkConnectionManager;
	private BlockingQueue<TrafficLightToTCCMessage> toBeSentMessagesQueue;
	private long lastChangeTimestamp;

	public ConnectedTrafficLight(SourceTrafficLightProxy proxy) {
		this.sourceTrafficLight = proxy;
		this.sourceTrafficLight.setDelegate(this);
		trafficLightsNetworkConnectionManager = new TrafficLightNetworkConnectionManager();
		toBeSentMessagesQueue = trafficLightsNetworkConnectionManager.getToBeSentMessagesQueue();
	}

	@Override
	public void onCurrentPhaseDurationChange(int duration) {

	}

	@Override
	public void onNextPhaseRemainingTimeChange(int remainingTime) {

		System.out.println("assumed next time to switch : " + remainingTime);
		/* when the phase changed , send the data to the TCC to inform it */

		/*
		 * inside the data there should be : the current phase; + the time this
		 * traffic light is expected to switch the color
		 */
		TrafficLightToTCCMessage message = new TrafficLightToTCCMessage();
		// message.setControlledLanes(sourceTrafficLight.getControlledLanes());
		message.setCurrentPhase(sourceTrafficLight.getCurrentPhase());
		message.setTrafficLightId(sourceTrafficLight.getId());
		message.setLastChangeTimestamp(lastChangeTimestamp);
		message.setExpectedPhaseChangeTime((long) remainingTime);
		message.setTccAddress(new InetSocketAddress(
				Constants.TEST_TCC_ADDRESS_HOST,
				Constants.TEST_TCC_FROM_TRAFFICLIGHT_ADDRESS_PORT));
		// message.setExpectedPhaseChangeTime(sourceTrafficLight.getAssumedTimeToNextSwitch());
		toBeSentMessagesQueue.offer(message);
	}

	@Override
	public void onPhaseChanged(int currentPhase) {

	}

	@Override
	public void onRYGStateChange(String RYGstate) {

		lastChangeTimestamp = System.currentTimeMillis();
		System.out.println("##################\ntraffic light ID : "
				+ sourceTrafficLight.getId() + " state : " + RYGstate + "\n\n");
	}

	@Override
	public void onSwitch() {

	}

	@Override
	public void onControlledLinksChange(Map<Integer, List<ControlledLink>> controlledLinks) {
		System.out.println("########## TL "+sourceTrafficLight.getId()+" CONTROLLED LINKS");
		for (Integer signal : controlledLinks.keySet()) {
			System.out.println("signal "+signal+" controls link : "+controlledLinks);
		}
	}

	@Override
	public void onCurrentProgramChanged(ConnectedTLProgram tlProgram) {

	}
}
